package com.xnx3.kefu.core.util;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;

import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestParam;

import com.xnx3.Lang;
//import com.aliyun.openservices.log.common.LogItem;
//import com.aliyun.openservices.log.exception.LogException;
//import com.xnx3.elasticsearch.ElasticSearchUtil;
import com.xnx3.j2ee.Global;
import com.xnx3.j2ee.util.ActionLogUtil;
import com.xnx3.j2ee.util.ApplicationPropertiesUtil;
import com.xnx3.j2ee.util.ConsoleUtil;
import com.xnx3.j2ee.util.ElasticSearchUtil;
import com.xnx3.j2ee.util.SystemUtil;
import com.xnx3.j2ee.util.actionLog.ElasticSearchMode;
import com.xnx3.j2ee.vo.ActionLogListVO;
import com.xnx3.net.AliyunLogUtil;

import cn.zvo.log.Log;
import cn.zvo.log.datasource.elasticsearch.ElasticSearchDataSource;
import cn.zvo.log.framework.springboot.LogUtil;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import com.xnx3.kefu.core.vo.MessageListVO;
import com.xnx3.kefu.core.vo.MessageReceiveVO;

/**
 * 消息存储相关。这里直接将消息推送到阿里云日志服务
 * @author 管雷鸣
 */
@Component(value="KefuCoreMessageStorageUtil")
public class MessageStorageUtil extends com.xnx3.j2ee.util.ActionLogUtil{
	public static String logstore = "message";	//专门存储message聊天记录的日志库名字
	public static AliyunLogUtil aliyunLogUtil;
//	public static ElasticSearchUtil esUtil;
	public static Log log;
	
	public static Log getLog() {
		if(log == null) {
			log = new Log();
			//加载es的配置 - 这是为了适配旧版本，新版本采用 https://github.com/xnx3/log 配置方式
			Object esHostName = ApplicationPropertiesUtil.getProperty("wm.elasticsearch.hostname");
			if(esHostName != null) {
				//v2.0之前的配置
				
				String hostname = esHostName.toString();
				if(hostname.length() > 0) {
					int port = Lang.stringToInt(ApplicationPropertiesUtil.getProperty("wm.elasticsearch.port"), 9200);
					String scheme = ApplicationPropertiesUtil.getProperty("wm.elasticsearch.scheme");
					if(scheme == null || scheme.length() == 0) {
						scheme = "http";
					}
					String username = ApplicationPropertiesUtil.getProperty("wm.elasticsearch.username");
					String password = ApplicationPropertiesUtil.getProperty("wm.elasticsearch.password");
					
					ElasticSearchDataSource datasource = new ElasticSearchDataSource(hostname, port, scheme, username, password, "");
					log.setDatasource(datasource);
				}
			}else {
				//v2.0之后用 https://gitee.com/mail_osc/log 的配置
				log = LogUtil.getLog().clone();
			}
			log.setTable(logstore);
		}
		return log;
	}
	
	
	/**
	 * 推送一条消息进来
	 * @param msg socket 接收到的消息，当socket接收到消息后，会立即推送过来
	 */
	public static void push(MessageReceiveVO msg){
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("type", msg.getType());
		map.put("extend", msg.getExtend() == null? "[]":msg.getExtend().toString());
		map.put("receiveId", msg.getReceiveId());
		map.put("sendId", msg.getSendId());
		map.put("text", msg.getText());
		map.put("time", msg.getTime());
		getLog().add(map);
		
//		if(esUtil != null) {
//			//使用的elasticsearch
//			Map<String, Object> map = new HashMap<String, Object>();
//			map.put("type", msg.getType());
//			map.put("extend", msg.getExtend() == null? "[]":msg.getExtend().toString());
//			map.put("receiveId", msg.getReceiveId());
//			map.put("sendId", msg.getSendId());
//			map.put("text", msg.getText());
//			map.put("time", msg.getTime());
//			esUtil.cache(map, logstore);
//			esUtil.cacheSubmit(logstore);
//			return;
//		}
//		
//		if(aliyunLogUtil != null) {
//			//使用的阿里云日志服务
//			LogItem logItem = new LogItem((int) (new Date().getTime() / 1000));
//			logItem.PushBack("type", msg.getType());
//			logItem.PushBack("extend", msg.getExtend() == null? "[]":msg.getExtend().toString());
//			logItem.PushBack("receiveId", msg.getReceiveId());
//			logItem.PushBack("sendId", msg.getSendId());
//			logItem.PushBack("text", msg.getText());
//			logItem.PushBack("time", msg.getTime()+"");
//			
//			try {
//				aliyunLogUtil.cacheLog(logItem);
//				//aliyunLogUtil.cacheCommit();
//			} catch (LogException e) {
//				e.printStackTrace();
//			}
//			return;
//		}
	}
	
	
	/**
	 * 查看我跟某人的历史聊天记录
	 * @param myChatid 当前我的chatid
	 * @param otherChatId 跟我聊天对方的chatid
	 * @param time 13位时间戳，要获取这个时间之前的记录
	 * @param number 要获取多少条记录，取值10~200之间，不传默认是100条
	 * @param type 类型，取数据的类型，可传入 before、after，  before:向前，也就是取<time的记录，after:向后,也就是取>time的记录 。默认不传则是before
	 */
	public static MessageListVO chatLog(String myChatid, String otherChatId, long time, int number, String type, HttpServletRequest request){
		MessageListVO vo = new MessageListVO();
		if(myChatid == null){
			vo.setBaseVO(MessageListVO.FAILURE, "没有发现你这个用户");
			return vo;
		}
		
		//参数校验
		if(number < 10){
			number = 10;
		}
		if(number > 200){
			number = 200;
		}
		if(otherChatId == null || otherChatId.length() == 0){
			vo.setBaseVO(MessageListVO.FAILURE, "请传入对方的chatid");
			return vo;
		}
		if(type == null || type.length() == 0){
			type = "before";
		}
		
		
//		if(!ActionLogUtil.isUse()){
//			vo.setBaseVO(MessageListVO.FAILURE, "未开启聊天持久化内容记录");
//			return vo;
//		}
		if(!(type.equalsIgnoreCase("before") || type.equalsIgnoreCase("after"))){
			vo.setBaseVO(MessageListVO.FAILURE, "type传入错误！请传入after、before");
			return vo;
		}
		
		//取列表
		
		if(getLog().isDataSource("ElasticSearchDataSource")) {
			//使用的 ElasticSearch
			String query = "((sendId="+myChatid+" AND receiveId="+otherChatId+") OR (sendId="+otherChatId+" AND receiveId="+myChatid+")) ";
			ElasticSearchDataSource datasource = (ElasticSearchDataSource) getLog().getDatasource();
			
			//获取查询结果的数据 
	    	SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    		QueryBuilder queryBuilder = QueryBuilders.queryStringQuery(query);
    		
    		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    		boolQueryBuilder.must(queryBuilder);
    		
    		if(type.equalsIgnoreCase("before")){
    			boolQueryBuilder.must(QueryBuilders.rangeQuery("time").lte(time-1));
			}else if(type.equalsIgnoreCase("after")){
				boolQueryBuilder.must(QueryBuilders.rangeQuery("time").gte(time+1));
			}
    		searchSourceBuilder.query(boolQueryBuilder);
    		searchSourceBuilder.sort(SortBuilders.fieldSort("time").order(SortOrder.DESC));
    		SearchResponse response = datasource.es.search(MessageStorageUtil.logstore, searchSourceBuilder, 0, number);
			
    		JSONArray array = new JSONArray();
	        if(response.status().getStatus() == 200){
	        	SearchHit shs[] = response.getHits().getHits();
	        	for (int i = 0; i < shs.length; i++) {
	        		Map<String, Object> map = shs[i].getSourceAsMap();
	        		//map.put("esid", shs[i].getId());
	        		array.add(JSONObject.fromObject(map));
				}
	        }else{
	        	//异常
	        	System.out.println("异常");
	        }
			vo.setList(array);
			
//			log.list(query, number, 1);
		}else {
			vo.setBaseVO(MessageListVO.FAILURE, "未启用 elasticsearch ，无法获取聊天记录");
			return vo;
		}
		
//		if(MessageStorageUtil.esUtil != null){
//			//使用的es
//		    
//		    //获取查询结果的数据 
//	    	SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//    		QueryBuilder queryBuilder = QueryBuilders.queryStringQuery(query);
//    		
//    		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//    		boolQueryBuilder.must(queryBuilder);
//    		
//    		if(type.equalsIgnoreCase("before")){
//    			boolQueryBuilder.must(QueryBuilders.rangeQuery("time").lte(time-1));
//			}else if(type.equalsIgnoreCase("after")){
//				boolQueryBuilder.must(QueryBuilders.rangeQuery("time").gte(time+1));
//			}
//    		searchSourceBuilder.query(boolQueryBuilder);
//    		searchSourceBuilder.sort(SortBuilders.fieldSort("time").order(SortOrder.DESC));
//    		SearchResponse response = MessageStorageUtil.esUtil.search(MessageStorageUtil.logstore, searchSourceBuilder, 0, number);
//			
//    		JSONArray array = new JSONArray();
//	        if(response.status().getStatus() == 200){
//	        	SearchHit shs[] = response.getHits().getHits();
//	        	for (int i = 0; i < shs.length; i++) {
//	        		Map<String, Object> map = shs[i].getSourceAsMap();
//	        		//map.put("esid", shs[i].getId());
//	        		array.add(JSONObject.fromObject(map));
//				}
//	        }else{
//	        	//异常
//	        	System.out.println("异常");
//	        }
//			vo.setList(array);
//		}else if(MessageStorageUtil.aliyunLogUtil != null){
//			if(type.equalsIgnoreCase("before")){
//				query = query + "AND time < "+time;
//			}else if(type.equalsIgnoreCase("after")){
//				query = query + "AND time > "+time;
//			}
//			
//
//			ActionLogListVO listVO = ActionLogUtil.list(MessageStorageUtil.logstore, query, number, request);
//			if(listVO.getResult() - ActionLogListVO.FAILURE == 0){
//				vo.setBaseVO(MessageListVO.FAILURE, listVO.getInfo());
//				return vo;
//			}
//			vo.setList(listVO.getJsonArray());
//		}
		
		vo.setEndTime(time);
		vo.setNumber(vo.getList().size());
		if(vo.getList().size() > 0){
			//如果有数据，那么取最后一条的时间
			JSONObject lastJson = vo.getList().getJSONObject(vo.getNumber() -1 );
			vo.setStartTime(getLong(lastJson, "time"));
		}
		
		//vo.setBaseVO(MessageListVO.FAILURE, "v2.0升级优化中，当前接口正在优化中，这几天就调试好了。");
		return vo;
	}
	
	/**
	 * 取json的long类型value
	 */
	private static long getLong(JSONObject json, String key){
		if(json.get(key) != null){
			return json.getLong(key);
		}
		return 0;
	}
}
